package beans.taskprocess;

import java.util.ArrayList;
import java.util.List;

/**
 * This is a FiLo (First in, last out) without priority
 * 
 * @author Razzek
 * @since 1.0
 * @see Task
 */
@SuppressWarnings("rawtypes")
public class TaskManager
{
	/**
	 * The list of tasks
	 **/
	private static final List $__taskList;
	/**
	 * The dispatcher of task (executor)
	 */
	private static final TaskDispatcher $__taskDispatcher;
	/**
	 * A Flag to indicate if the module is stopped
	 */
	private static boolean $__isStoped;

	static
	{
		// the reference to the main thread, i don't need know this reference later.
		final Thread thread;
		// The group of the threads
		final ThreadGroup threadGroup;

		// i don't need synchronization, then i use an ArrayList.
		$__taskList = new ArrayList();
		// this must be a parameter. I need obtain some of this in a parameter form.
		$__taskDispatcher = new TaskDispatcher(9, (Thread.NORM_PRIORITY + Thread.MAX_PRIORITY) / 2, 1000);
		// A new group for have the full control of the child threads
		threadGroup = new ThreadGroup("TaskManager");
		// this is the main thread of the TaskManager.
		thread = new Thread(threadGroup, $__taskDispatcher, "Main");
		// this end when the last of the child threads end
		thread.setDaemon(false);
		thread.start();
		// The system is up and ready
		$__isStoped = false;
	}

	/**
	 * Adds a Task without a timeout
	 * 
	 * @param task
	 *            The task to execute
	 * 
	 * @throws IllegalStateException
	 *             If the system is down
	 */
	public static void addTask(Task task)
	{
		// check if the system is down ...
		if ($__isStoped)
			throw new IllegalStateException();
		synchronized ($__taskList)
		{
			__addTask(task, -1);
		}
	}

	/**
	 * Adds a Task with the specified a timeout
	 * 
	 * @param task
	 *            The task to execute
	 * @param timeout
	 *            The time limit for execute the task
	 * 
	 * @throws IllegalStateException
	 *             If the system is down
	 */
	public static void addTask(Task task, long timeout)
	{
		// check if the system is down ...
		if ($__isStoped)
			throw new IllegalStateException();
		synchronized ($__taskList)
		{
			__addTask(task, timeout);
		}
	}

	public static void addTasks(Task[] tasks)
	{
		addTasks(tasks, -1);
	}

	public static void addTasks(Task[] tasks, long timeout)
	{
		// check if the system is down ...
		if ($__isStoped)
			throw new IllegalStateException();
		synchronized ($__taskList)
		{
			int i;
			int length;

			length = tasks.length;
			for (i = 0; i < length; i++)
				__addTask(tasks[i], timeout);
		}
	}

	public static void addTasks(List tasks)
	{
		addTasks(tasks, 2000);
	}

	public static void addTasks(List tasks, long timeout)
	{
		// check if the system is down ...
		if ($__isStoped)
			throw new IllegalStateException();
		synchronized ($__taskList)
		{
			int i;
			int length;

			length = tasks.size();
			for (i = 0; i < length; i++)
				__addTask((Task) tasks.get(i), timeout);
		}
	}

	public static void shutdown()
	{
		$__isStoped = true;
		synchronized ($__taskList)
		{
			$__taskDispatcher.stop();
		}
	}

	static boolean hasTask()
	{
		synchronized ($__taskList)
		{
			return $__taskList.size() > 0;
		}
	}

	static TaskNode getTaskNode()
	{
		// check if the system is down ...
		if ($__isStoped)
			throw new IllegalStateException();
		synchronized ($__taskList)
		{
			return (TaskNode) $__taskList.remove(0);
		}
	}

	@SuppressWarnings("unchecked")
	private static void __addTask(Task task, long timeout)
	{
		if (!$__taskList.contains(task))
			$__taskList.add(new TaskNode(task, timeout));
	}
}
